package org.oy.sealogger.ui;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.image.ImageObserver;
import java.util.Observable;
import java.util.Observer;

import org.oy.sealogger.parser.RMCSentence;

import org.oy.sealogger.parser.CurrentState;

public class Compass implements Observer {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1047230784217517315L;
	
	private Image compass;
	private Image direction;
	private ImageLoader imageLoader = new ImageLoader();
	private LoggerGraphics lg = null;
	
	private int directionLabelX;
	private int tempX, tempY, tempW, tempH;
	
	private double currentAngle = 0.0;
	
	
	
	public Compass(LoggerGraphics l) {
		this.lg = l;
		
		compass = imageLoader.getImage("COMPASS.png");
		direction = imageLoader.getImage("direction.png");
	}
	
	public void setTempVariables(int x, int y, int w, int h) {
		this.tempX = x;
		this.tempY = y;
		this.tempW = w;
		this.tempH = h;
	}
	
	
	public void draw(Graphics g, int x, int y, int w, int h) {
		Graphics2D g2 = (Graphics2D)g;
		
		Point p = this.getCompassCenter(x,y,w,h);
		this.setCompassRotation(g2,0.0,p);	
		
		this.drawCompass(g2,this.imageLoader,x,y,w,h);
		this.setLabelX(x,y,w,h);
		this.setDirectionLabel(g2,y,h);
		this.drawDirection(g2,this.imageLoader,x,y,w,h);
		
		setTempVariables(x,y,w,h);
	}
	
	public void drawCompass(Graphics2D g, ImageObserver imgObs, int x, int y, 
							int w, int h) {	
		
		g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.8f));
		g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
		g.drawImage(compass,x,y,w,h, imgObs);		
	}
	
	public void drawDirection(Graphics2D g, ImageObserver imgObs, int x, int y,
							int w, int h) {
		
		int wd = (int)(Math.round(0.14 * w));
		int hd = (int)(Math.round(0.11 * h));
		int yspace = (int)(Math.round(0.12 * h));
		
		int xd = x + (w / 2) - (wd / 2);
		int yd = y + yspace;
				
		Point p = this.getCompassCenter(x,y,w,h);
		this.setCompassRotation(g,this.currentAngle,p);	
		
		g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.8f));
		g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
		g.drawImage(direction,xd,yd,wd,hd, imgObs);		
	}
	
	
	public void setCompassRotation(Graphics2D g2, double angle, Point p) {
    	AffineTransform at;
    	at = new AffineTransform();
    	at.rotate(Math.toRadians(angle), p.x, p.y);
    	g2.setTransform(at);
	}
	
	public void setLabelX(int x, int y, int w, int h) {
		Point p = this.getCompassCenter(x,y,w,h);
		
    	if (this.currentAngle < 10.0) {
    		int center1 = (int)(Math.round(0.12 * w));
    		this.directionLabelX = p.x - center1;
    	}
    	
    	if (this.currentAngle >= 10.0 && this.currentAngle < 100.0) {
    		int center2 = (int)(Math.round(0.17 * w));
    		this.directionLabelX = p.x - center2;
    	}
    	
    	if (this.currentAngle >= 100.0) {
    		int center3 = (int)(Math.round(0.22 * w));
    		this.directionLabelX = p.x - center3;   	
    	}
    }
	
	public void setDirectionLabel(Graphics2D g2,int y, int h) {
    	String dir = Double.toString(this.currentAngle);
    	
    	int fontSize = (int)(Math.round(0.17 * h));
    	int yCenter = (int)(Math.round(0.05 * h));
    	int yl = y + (h / 2) + yCenter;
    	
        g2.setPaint(Color.BLACK);
		g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f));
		g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        g2.setFont(new Font("Arial", Font.BOLD, fontSize));
        g2.drawString(dir, this.directionLabelX,yl);		
    }
	
	public Point getCompassCenter(int x, int y, int w, int h) {
		Point p = new Point();
		
		int tempX = w / 2;
		int tempY = h / 2;
		p.x = (x + tempX);
		p.y = (y + tempY);
		
		return p;
	}
		
	public void setAngle(double angle) {
		this.currentAngle = angle;
		
		setLabelX(this.tempX,this.tempY,this.tempW,this.tempH);
		this.lg.repaint();
	}

	public void update(Observable state, Object arg) {
		RMCSentence rmc = ((CurrentState)state).getGPSLocation();
		
		setAngle(rmc.getTrack());
	}
		
}
